package com.hxgis.common.service.impl;

import com.es.common.EsAggCondition;
import com.es.common.domain.EsCondition;
import com.es.wrapper.DataWrapper;
import com.hxgis.common.base.ResultVO;
import com.hxgis.common.base.StationCache;
import com.hxgis.common.entity.RainDayInfo;
import com.hxgis.common.entity.RainstormFeatureInfo;
import com.hxgis.common.entity.RainstormInfo;
import com.hxgis.common.entity.Station;
import com.hxgis.common.repository.RainDayInfoRepository;
import com.hxgis.common.repository.RainstormFeatureInfoRepository;
import com.hxgis.common.repository.RainstormInfoRepository;
import com.hxgis.common.repository.StationInfoRepository;
import com.hxgis.common.service.RainstormFeatureService;
import com.hxgis.common.service.RainstormInfoService;
import com.hxgis.common.service.StationService;
import com.hxgis.common.service.graph.RainStormGraph;
import com.hxgis.common.utils.*;
import com.hxgis.common.utils.quickhull.QuickHull;
import com.hxgis.common.utils.quickhull.datastructures.LinkedList;
import com.hxgis.common.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.geojson.FeatureCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class RainstormInfoServiceImpl implements RainstormInfoService {

    @Value("${save.coursePath}")
    private String coursePath;

    @Autowired
    RainDayInfoRepository rainDayInfoRepository;

    @Autowired
    RainstormInfoRepository rainstormInfoRepository;

    @Autowired
    StationInfoRepository stationInfoRepository;

    @Autowired
    StationService stationService;

    @Autowired
    private RainstormFeatureInfoRepository featureInfoRepository;

    @Autowired
    private RainstormFeatureService featureService;

    @Autowired
    private RainStormGraph rainStormGraph;

    /**
     * 批量将某年段时间数据按月分插入暴雨表 因为如果一年一跑数据会很多影响性能所以将时间分成年月每月跑并存es
     * 到时候定时器跑的时候 其它输入的是年月日 切分成年传进来
     * @param startYear
     * @param endYear
     */
    @Override
    public void initRainstormInfoToEs(String startYear, String endYear) {
        List<Station> stations = StationCache.getStations();
        for (int i = Integer.valueOf(startYear); i <= Integer.valueOf(endYear); i++) {
            for (int j = 1; j <= 12 ; j++){
                saveStorms(TimeUtil.getFirstDayOfMonth(i,j), TimeUtil.getLastDayOfMonth(i,j), RectField.getBeanFields(stations,"stationNo"));
            }
        }
        log.info("{},到{}的暴雨基础原数据保存到暴雨表",startYear,endYear);
    }

    /**
     * 从日值表将暴雨数据存入暴雨表
     * @param startTime
     * @param endTime
     */
    @Override
    public void saveStorms(String startTime, String endTime, List<String> stationNos) {
        List<RainstormInfo> rainstormInfos = new ArrayList<>();
        EsCondition esCondition = EsCondition.getEsCondition();
        esCondition.gte("rainFall",500).lte(20000);
        esCondition.in("stationNo",stationNos);
        esCondition.gte("time", startTime).lte(endTime);
        esCondition.size(1000000);
        List<RainDayInfo> rainDayInfos = rainDayInfoRepository.selectList(esCondition);
        if (!CollectionUtils.isEmpty(rainDayInfos)){
            rainDayInfos.stream().forEach(x -> {
                RainstormInfo rainstormInfo = new RainstormInfo();
                rainstormInfo.setDays(x.getDays());
                rainstormInfo.setId(x.getId());
                rainstormInfo.setRainFall(x.getRainFall());
                rainstormInfo.setStationNo(x.getStationNo());
                rainstormInfo.setTime(x.getTime().intValue());
                rainstormInfo.setYear(x.getYear());
                rainstormInfos.add(rainstormInfo);
            });
        }
        rainstormInfoRepository.saveBatch(rainstormInfos);
    }

    @Override
    public void transSingleStrom(String startTime, String endTime) {
        //查询出所有的站点
        List<Station> stations = StationCache.getStations();
        //todo 优化
        EsCondition rainStormCondition = EsCondition.getEsCondition();
        rainStormCondition.gte("time",Long.parseLong(startTime)).lte(Long.parseLong(endTime));
        rainStormCondition.size(1000000);
        List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(rainStormCondition);
        Map<String, List<RainstormInfo>> stationMap = rainstormInfos.stream().collect(Collectors.groupingBy(RainstormInfo::getStationNo));
        stationMap.forEach((stationNo,rainstormInfoList) -> {
            if (!CollectionUtils.isEmpty(rainstormInfoList)){
                //todo 必须按照时间排序 因为第一天要去找前面的，如果时间不是按照排序的来的话，可能出现错乱现象
                Collections.sort(rainstormInfoList,(a, b) ->{
                    return (int)(a.getTime() - b.getTime());
                });
                List<RainstormInfo> rainstormInfos1 = new ArrayList<>();
                //判断是否为空
                rainstormInfos1 = transSingleStrom(rainstormInfoList);

                rainstormInfoRepository.saveBatch(rainstormInfos1);
            }
         });

        //遍历所有的站点
//        stations.stream().forEach(x -> {
//            EsCondition rainStormCondition = EsCondition.getEsCondition();
//            rainStormCondition.gte("time",Long.parseLong(startTime)).lte(Long.parseLong(endTime));
//            rainStormCondition.eq("stationNo",x.getStationNo());
//            rainStormCondition.size(100000);
//            //查询出单站的所有暴雨事件
//            List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(rainStormCondition);
//            //todo 必须按照时间排序 因为第一天要去找前面的，如果时间不是按照排序的来的话，可能出现错乱现象
//            Collections.sort(rainstormInfos,(a, b) ->{
//               return (int)(a.getTime() - b.getTime());
//            });
////            System.out.println(rainstormInfos.size());
//            List<RainstormInfo> rainstormInfos1 = new ArrayList<>();
//            //判断是否为空
//            if(!CollectionUtils.isEmpty(rainstormInfos)){
//                rainstormInfos1 = transSingleStrom(rainstormInfos);
//            }
//            rainstormInfoRepository.saveBatch(rainstormInfos1);
//        });
        log.info("{}到{}单站暴雨事件保存完成",startTime,endTime);
    }


    /**
     * 根据时间查询站点
     * @param time
     * @return
     */
    @Override
    public RainstormInfo queryByTime(Long time,String stationNo) {
        EsCondition rainStormCondition = EsCondition.getEsCondition();
        rainStormCondition.eq("time",time);
        rainStormCondition.eq("stationNo",stationNo);
        rainStormCondition.size(100000);
        List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(rainStormCondition);
        return CollectionUtils.isEmpty(rainstormInfos) ? null : rainstormInfos.get(0);
    }




    @Override
    public void transAreaStrom(String startTime, String endTime) {
        List<Station> stationList = stationService.selectAll();
        List<String> stationNoList = RectField.getBeanFields(stationList, "stationNo");

        EsAggCondition esAggCondition = EsAggCondition.getInstance();
        esAggCondition.Group("courseNum").size(100000);
        esAggCondition.getEsCondition().gte("time", Long.valueOf(startTime)).lte(Long.valueOf(endTime))
//                .LT("time", Long.valueOf(endTime))
                .in("stationNo", com.hxgis.common.utils.CollectionUtils.convertCollectionString(stationNoList))
                .eq("courseNum",null).not();
        List<String> courseNumList = rainstormInfoRepository.selectListAgg(esAggCondition, new DataWrapper<String>() {
            @Override
            public String wrapper(Map<String, Object> data) {
                return (String) data.get("courseNum");
            }
        });
        EsCondition courseNumCondition = EsCondition.getEsCondition();
        courseNumCondition.in("courseNum", com.hxgis.common.utils.CollectionUtils.convertCollectionString(courseNumList));
        courseNumCondition.size(100000);
        List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(courseNumCondition);
        Map<String, RainstormInfo> collect = rainstormInfos.stream().collect(Collectors.toMap(RainstormInfo::getCourseNum, k -> k));
        collect.forEach((k,v) -> {

        });

    }

    /**
     * 根据开始时间结束时间类型分析数据
     * @param startTime
     * @param endTime
     * @param type
     * @return
     */
    @Override
    public ResultVO analysisByTarget(String startTime, String endTime, Integer type) {
        Long stLog = System.currentTimeMillis();
        EsAggCondition esAggCondition = EsAggCondition.getInstance();
        esAggCondition.Group("courseArea").sum("rainFall","sum").size(100000);
        EsCondition esCondition = esAggCondition.getEsCondition();
        esCondition.eq("courseArea",null).not();
        esCondition.eq("courseNum",null).not();
        esCondition.gte("time",Long.parseLong(startTime)).lte(Long.parseLong(endTime));
//        esCondition.lte("time",Long.parseLong(endTime));
        List<RainStormAggVO> rainStormAggVOS1 = rainstormInfoRepository.selectListAgg(esAggCondition, new DataWrapper<RainStormAggVO>() {
            @Override
            public RainStormAggVO wrapper(Map<String, Object> data) {
                RainStormAggVO rainStormAggVO = new RainStormAggVO();
                rainStormAggVO.setCourseArea(data.get("courseArea").toString());
                rainStormAggVO.setSum(Double.parseDouble(data.get("sum").toString()));
                return rainStormAggVO;
            }
        });
        //取出结果集
        List<AnalysisVO> analysis = new ArrayList<>();
        if (!CollectionUtils.isEmpty(rainStormAggVOS1)){
//            List<RainStormAggVO> rainStormAggVOS = stringListMap.get("courseAgg");
            Collections.sort(rainStormAggVOS1,(a,b) -> {
                return new BigDecimal(b.getSum()).compareTo(new BigDecimal(a.getSum()));
            });
            analysis = getAnalysis(rainStormAggVOS1);
        }

        Collections.sort(analysis,(a,b) -> {
            return (int)(Double.parseDouble(b.getStartTime()) - Double.parseDouble(a.getStartTime()));
        });

        for (int i = 0; i < analysis.size(); i++) {
            analysis.get(i).setRange(i + 1);
        }
        log.info("查询第一种指标指标用时,{},总过程数量:{}",System.currentTimeMillis() - stLog,analysis.size());

        //todo 画图
//        try {
//            rainStormGraph.genRainStormArea(coursePath, startTime, endTime, analysis);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }

        return ResultVOUtil.success(analysis);
    }

    /**
     * 画动画
     * @param courseArea
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public ResultVO getCourseAnimation(String courseArea, String startTime, String endTime) {
        long start = System.currentTimeMillis();
//        Map<String, Station> stringStationMap = stationService.queryAllStation();
        Map<String, Station> stringStationMap = StationCache.getStationInfoMap();
        Map<String, LinkedList> map = stationService.queryAllStationAffect();
        EsCondition rainStormCondition = EsCondition.getEsCondition();
        rainStormCondition.eq("courseArea", courseArea);
        rainStormCondition.size(1000000);
        List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(rainStormCondition);
        Collections.sort(rainstormInfos, (a,b) -> {
            return (int)(a.getTime() - b.getTime());
        });
        Map<Long, List<RainstormInfo>> collect = rainstormInfos.stream().collect(Collectors.groupingBy(RainstormInfo::getTime));

        /**
         * 循环时间
         */
        List<String> monthBetweenDateStr = new ArrayList<>();
        try {
            monthBetweenDateStr = TimeUtil.getMonthBetweenDateStr(TimeUtil.preDay(startTime, 1, TimeUtil.FORMATOR_YMD),
                    TimeUtil.nextDay(endTime, 1, TimeUtil.FORMATOR_YMD));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //返回list封装
        List<AnimationVO> animationVOS = new ArrayList<>();
        log.info("数据准备用时:{}",System.currentTimeMillis() - start);
        for (int i = 0; i < monthBetweenDateStr.size(); i++) {
            AnimationVO animationVO = new AnimationVO();
            animationVO.setRange(i + 1);
            animationVO.setNowDate(monthBetweenDateStr.get(i));
            List<RainstormInfo> rainstormInfos1 = collect.get(Long.valueOf(monthBetweenDateStr.get(i)));
            //计算边界
            QuickHull quickHull = new QuickHull();
            com.hxgis.common.utils.quickhull.datastructures.LinkedList pointSet = new LinkedList();
            String type = "";
            List<StationVO> stationVOS = new ArrayList<>();
            rainstormInfos1.stream().forEach(x -> {
                pointSet.insertAll(map.get(x.getStationNo()));
                StationVO stationVO = new StationVO();
                stationVO.setStationNo(x.getStationNo());
                stationVO.setLat(Double.valueOf(stringStationMap.get(x.getStationNo()).getLat()));
                stationVO.setLon(Double.valueOf(stringStationMap.get(x.getStationNo()).getLon()));
                stationVOS.add(stationVO);
//                pointSet.insert(new Point2D.Double(Double.valueOf(stringStationMap.get(x.getStationNo()).getLon()),Double.valueOf(stringStationMap.get(x.getStationNo()).getLat())));
            });
            log.info("查询动画时间:{}",System.currentTimeMillis() - start);
            LinkedList calcPointsSet = quickHull.useAlgorithm(pointSet);
            FeatureCollection draw = GeoUtil.draw(calcPointsSet, monthBetweenDateStr.get(i));
            animationVO.setFeatureCollection(draw);
            animationVO.setStationVOS(stationVOS);
            animationVOS.add(animationVO);

        }
        return ResultVOUtil.success(animationVOS);
    }




    @Override
    public ResultVO copyAnalysisByTarget(String startTime, String endTime) {
        Long stLog = System.currentTimeMillis();
        EsAggCondition esAggCondition = EsAggCondition.getInstance();
        esAggCondition.Group("courseArea").sum("rainFall","sum").size(10000);
        EsCondition esCondition = esAggCondition.getEsCondition();
        esCondition.eq("courseArea",null).not();
        esCondition.eq("courseNum",null).not();
        esCondition.gte("time",Long.parseLong(startTime)).lte(Long.parseLong(endTime));
//        esCondition.lte("time",Long.parseLong(endTime));
        List<RainStormAggVO> rainStormAggVOS1 = featureInfoRepository.selectListAgg(esAggCondition, new DataWrapper<RainStormAggVO>() {
            @Override
            public RainStormAggVO wrapper(Map<String, Object> data) {
                RainStormAggVO rainStormAggVO = new RainStormAggVO();
                rainStormAggVO.setSum(Double.parseDouble(data.get("sum").toString()));
                rainStormAggVO.setCourseArea(data.get("courseArea").toString());
                return rainStormAggVO;
            }
        });
        //取出结果集
        List<AnalysisVO> analysis = new ArrayList<>();
        if (!CollectionUtils.isEmpty(rainStormAggVOS1)){
//            List<RainStormAggVO> rainStormAggVOS = stringListMap.get("courseAgg");
            Collections.sort(rainStormAggVOS1,(a,b) -> {
                return new BigDecimal(b.getSum()).compareTo(new BigDecimal(a.getSum()));
            });
            analysis = getCopyAnalysis(rainStormAggVOS1);
        }

        Collections.sort(analysis,(a,b) -> {
            return (int)(Double.parseDouble(b.getStartTime()) - Double.parseDouble(a.getStartTime()));
        });

        for (int i = 0; i < analysis.size(); i++) {
            analysis.get(i).setRange(i + 1);
        }
        log.info("查询第三种指标指标用时,{},总过程数量:{}",System.currentTimeMillis() - stLog,analysis.size());

        return ResultVOUtil.success(analysis);
    }

    @Override
    public ResultVO getCopyCourseAnimation(String courseArea, String startTime, String endTime) {
        long start = System.currentTimeMillis();
        Map<String, Station> stringStationMap = StationCache.getStationInfoMap();
        Map<String, LinkedList> map = stationService.queryAllStationAffect();
        EsCondition rainFeaturemCondition = EsCondition.getEsCondition();
        rainFeaturemCondition.eq("courseArea", courseArea);
        rainFeaturemCondition.size(1000000);
        List<RainstormFeatureInfo> featureInfos = featureInfoRepository.selectList(rainFeaturemCondition);
        Collections.sort(featureInfos, (a,b) -> {
            return (int)(a.getTime() - b.getTime());
        });
        Map<Long, List<RainstormFeatureInfo>> collect = featureInfos.stream().collect(Collectors.groupingBy(RainstormFeatureInfo::getTime));

        /**
         * 循环时间
         */
        List<String> monthBetweenDateStr = new ArrayList<>();
        try {
            monthBetweenDateStr = TimeUtil.getMonthBetweenDateStr(TimeUtil.preDay(startTime, 1, TimeUtil.FORMATOR_YMD),
                    TimeUtil.nextDay(endTime, 1, TimeUtil.FORMATOR_YMD));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //返回list封装
        List<AnimationVO> animationVOS = new ArrayList<>();
        log.info("数据准备用时:{}",System.currentTimeMillis() - start);
        for (int i = 0; i < monthBetweenDateStr.size(); i++) {
            AnimationVO animationVO = new AnimationVO();
            animationVO.setRange(i + 1);
            animationVO.setNowDate(monthBetweenDateStr.get(i));
            List<RainstormFeatureInfo> rainstormInfos1 = collect.get(Long.valueOf(monthBetweenDateStr.get(i)));
            //计算边界
            QuickHull quickHull = new QuickHull();
            com.hxgis.common.utils.quickhull.datastructures.LinkedList pointSet = new LinkedList();
            String type = "";
            List<StationVO> stationVOS = new ArrayList<>();
            rainstormInfos1.stream().forEach(x -> {
                pointSet.insertAll(map.get(x.getStationNo()));
                StationVO stationVO = new StationVO();
                stationVO.setLat(Double.valueOf(stringStationMap.get(x.getStationNo()).getLat()));
                stationVO.setLon(Double.valueOf(stringStationMap.get(x.getStationNo()).getLon()));
                stationVO.setStationNo(x.getStationNo());
                stationVOS.add(stationVO);
            });
            log.info("查询动画时间:{}",System.currentTimeMillis() - start);
            LinkedList calcPointsSet = quickHull.useAlgorithm(pointSet);
            FeatureCollection draw = GeoUtil.draw(calcPointsSet, monthBetweenDateStr.get(i));
            animationVO.setFeatureCollection(draw);
            animationVO.setStationVOS(stationVOS);
            animationVOS.add(animationVO);
        }
        return ResultVOUtil.success(animationVOS);
    }

    @Override
    public ResultVO queryAnalysisVO(String courseArea, String startTime, String endTime, Integer flag) {
        List<String> arreaStations = new ArrayList<>();
        if (Objects.equals(flag,1)){
            EsCondition rainstormCondition = EsCondition.getEsCondition();
            rainstormCondition.eq("courseArea",courseArea);
            rainstormCondition.size(1000000);
            List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(rainstormCondition);
            arreaStations = rainstormInfos.stream().map(RainstormInfo::getStationNo).collect(Collectors.toList());
        }
        if (Objects.equals(flag,2)){
            EsCondition featureCondition = EsCondition.getEsCondition();
            featureCondition.eq("courseArea",courseArea);
            featureCondition.size(1000000);
            List<RainstormFeatureInfo> featureInfos = featureInfoRepository.selectList(featureCondition);
            arreaStations = featureInfos.stream().map(RainstormFeatureInfo::getStationNo).collect(Collectors.toList());
        }
        EsCondition stationCondition = EsCondition.getEsCondition();
        stationCondition.in("stationNo", com.hxgis.common.utils.CollectionUtils.convertCollectionString(arreaStations));
        stationCondition.gte("time", Long.valueOf(startTime))
                .lte(Long.valueOf(endTime))
                .lte("rainFall",10000);
        stationCondition.size(1000000);
        List<RainDayInfo> rainDayInfos = rainDayInfoRepository.selectList(stationCondition);
        Map<String, DoubleSummaryStatistics> collect1 = rainDayInfos.stream().collect(Collectors.groupingBy(RainDayInfo::getStationNo,
                Collectors.summarizingDouble(RainDayInfo::getRainFall)));
        List<DoubleSummaryStatistics> doubleSummaryStatisticsList = new ArrayList<>();
        collect1.forEach((k1,v1) -> {
            doubleSummaryStatisticsList.add(collect1.get(k1));
        });
        AnalysisVO analysisVO = new AnalysisVO();
        //最大累计降水量
        Collections.sort(doubleSummaryStatisticsList,(a, b) -> {
            return new BigDecimal(b.getSum()).compareTo(new BigDecimal(a.getSum()));
        });
        analysisVO.setMaxTotalRainfall(NumUtil.save2Point(doubleSummaryStatisticsList.get(0).getSum() / 10));
        analysisVO.setMinTotalRainfall(NumUtil.save2Point(doubleSummaryStatisticsList.get(doubleSummaryStatisticsList.size() - 1).getSum() / 10));
        Double totalRainFall = new Double(0);
        for (DoubleSummaryStatistics doubleSummaryStatistics : doubleSummaryStatisticsList) {
            totalRainFall += doubleSummaryStatistics.getSum()/10;
        }
        analysisVO.setAvgTotalRainfall(NumUtil.save2Point(totalRainFall/doubleSummaryStatisticsList.size() + 1));
        return ResultVOUtil.success(analysisVO);
    }


    private List<AnalysisVO> getCopyAnalysis(List<RainStormAggVO> rainStormAggVOS) {
        Map<String, Station> stringStationMap = StationCache.getStationInfoMap();
        //站点影响区域
        Map<String, LinkedList> map = stationService.queryAllStationAffect();
        List<AnalysisVO> analysisVOS = new ArrayList<>();
        Map<String, List<RainstormFeatureInfo>> rainstormsByCourseAreas = this.getCopyRainstormsByCourseAreas(rainStormAggVOS);
        //单站点相关信息
//        Map<String, List<AffectStationInfoVO>> groupByStationNo = groupCopyByStationNo(rainStormAggVOS,stringStationMap);
        Map<String, List<Station>> boundNumMap = getBoundNum();
        //优化后，如果不对删掉
//        Map<String, List<AnalysisVO>> analysVos = getAnalysVos(rainStormAggVOS,stringStationMap);

        for (int i = 0; i < rainStormAggVOS.size(); i++) {
            RainStormAggVO rainStormAggVO = rainStormAggVOS.get(i);

            List<RainstormFeatureInfo> rainstormInfos = rainstormsByCourseAreas.get(rainStormAggVO.getCourseArea());
            Collections.sort(rainstormInfos,(a, b) -> {
                return (int)(a.getTime() - b.getTime());
            });
            //开始时间
            String startTime = String.valueOf(rainstormInfos.get(0).getTime());
            //结束时间
            String endTime = String.valueOf(rainstormInfos.get(rainstormInfos.size() - 1).getTime());
            //持续天数
            int continueDays = TimeUtil.getDaysBetween2Date(startTime, endTime);


            //优化前
            AnalysisVO analysisVO = this.getCopyAnalysVos(rainStormAggVO.getCourseArea(), rainstormsByCourseAreas, startTime, endTime, continueDays);
//            AnalysisVO analysisVO =  new AnalysisVO();
            //优化后 可以和上面换
//            AnalysisVO analysisVO = analysVos.get(rainStormAggVO.getCourseArea()).get(0);


//            List<AffectStationInfoVO> affectStationInfoVOS = groupByStationNo.get(rainStormAggVO.getCourseArea());


            Map<String, DoubleSummaryStatistics> collect2 = rainstormInfos.stream().collect(Collectors.groupingBy(RainstormFeatureInfo::getStationNo,
                    Collectors.summarizingDouble(RainstormFeatureInfo::getRainFall)));

            List<AffectStationInfoVO> affectStationInfoVOS = new ArrayList<>();
            Collections.sort(rainstormInfos,(a, b) -> {
                return (int)(a.getTime() - b.getTime());
            });
            //根据站点分组
            Map<String, List<RainstormFeatureInfo>> collect1 = rainstormInfos.stream()
                    .collect(Collectors.groupingBy(RainstormFeatureInfo::getStationNo));
            collect1.forEach((k1,v1) -> {
                String stationNo = v1.get(0).getStationNo();
                Long st = v1.get(0).getTime();
                Long ed = v1.get(v1.size()-1).getTime();
                //单站数据
                AffectStationInfoVO affectStationInfoVO = new AffectStationInfoVO();
                affectStationInfoVO.setStationNo(stationNo);
                affectStationInfoVO.setStartTime(String.valueOf(st));
                affectStationInfoVO.setEndTime(String.valueOf(ed));
                affectStationInfoVO.setLat(Double.parseDouble(stringStationMap.get(stationNo).getLat()));
                affectStationInfoVO.setLon(Double.parseDouble(stringStationMap.get(stationNo).getLon()));
                affectStationInfoVO.setContinueDays(TimeUtil.getDaysBetween2Date(String.valueOf(st), String.valueOf(ed)));
                affectStationInfoVO.setTotalRainfall(NumUtil.save2Point(collect2.get(stationNo).getSum()/10));
                affectStationInfoVO.setAvgArea(NumUtil.save2Point(collect2.get(stationNo).getSum()/10/TimeUtil.getDaysBetween2Date(String.valueOf(st), String.valueOf(ed))));
                affectStationInfoVOS.add(affectStationInfoVO);
            });


            Collections.sort(affectStationInfoVOS,(a, b) -> {
//                return new BigDecimal(a.getStartTime()).subtract(new BigDecimal(b.getStartTime())).intValue();
                return (int)(Double.parseDouble(a.getStartTime()) - Double.parseDouble(b.getStartTime()));
            });
            //区域最小
            Collections.sort(affectStationInfoVOS,(a, b) -> {
                return (int)(a.getAvgArea() - b.getAvgArea());
            });
            analysisVO.setMinArea(affectStationInfoVOS.get(0).getAvgArea());

            //区域最大
            analysisVO.setMaxArea(affectStationInfoVOS.get(affectStationInfoVOS.size() - 1).getAvgArea());
            //todo 区域平均

            DoubleSummaryStatistics collect = affectStationInfoVOS.stream().collect(Collectors.summarizingDouble(AffectStationInfoVO::getAvgArea));
            analysisVO.setAvgArea(NumUtil.save2Point(collect.getAverage()));


            //计算边界
            QuickHull quickHull = new QuickHull();
            LinkedList pointSet = new LinkedList();
            List<Double> lats = new ArrayList<>();
            List<String> gridNums = new ArrayList<>();

            //循环所有影响的站点画圈圈
            BigDecimal afffectArea = new BigDecimal(0);
            for (int j = 0; j < affectStationInfoVOS.size(); j++) {
                AffectStationInfoVO affectStationInfoVO = affectStationInfoVOS.get(j);
                affectStationInfoVO.setRange(j+1);
                String gridNum = stringStationMap.get(affectStationInfoVO.getStationNo()).getGridNum();
                pointSet.insertAll(map.get(affectStationInfoVO.getStationNo()));
                List<Station> stations = boundNumMap.get(gridNum);
                double v = DistanceUtil.countArea(Double.parseDouble(stringStationMap.get(affectStationInfoVO.getStationNo()).getLat()));
                BigDecimal bigDecimal2 = new BigDecimal(v / stations.size());
                afffectArea = afffectArea.add(bigDecimal2);
            }

            LinkedList calcPointsSet = quickHull.useAlgorithm(pointSet);
            FeatureCollection draw = GeoUtil.draw(calcPointsSet, rainStormAggVO.getCourseArea());
            analysisVO.setFeatureCollection(draw);


            analysisVO.setAfffectArea(NumUtil.save2Point(afffectArea.doubleValue()));
            //todo 平均降水量以过程的总降水量为主 不再是暴雨数据这张表了
//            double avgTotalRainfall = rainStormAggVO.getSum() /10 / affectStationInfoVOS.size()+1;

            //封装返回结果集
            analysisVO.setAffectStationInfoVOS(affectStationInfoVOS).setCourseArea(rainStormAggVO.getCourseArea())
                    .setContinueDays(continueDays).setStartTime(startTime).setEndTime(endTime);
            analysisVOS.add(analysisVO);
        }
        return analysisVOS;
    }

    private List<AnalysisVO> getAnalysis(List<RainStormAggVO> rainStormAggVOS) {
        Map<String, Station> stringStationMap = StationCache.getStationInfoMap();
        //站点影响区域
        Map<String, LinkedList> map = stationService.queryAllStationAffect();
        List<AnalysisVO> analysisVOS = new ArrayList<>();
        //todo 到时候区分什么型降水在这里区分 筛选站点出来in查询
        Map<String, List<RainstormInfo>> rainstormsByCourseAreas = this.getRainstormsByCourseAreas(rainStormAggVOS);
        //单站点相关信息
        //todo 到时候区分什么型降水在这里区分 筛选站点出来in查询
//        Map<String, List<AffectStationInfoVO>> groupByStationNo = groupByStationNo(rainStormAggVOS,stringStationMap);
        Map<String, List<Station>> boundNumMap = getBoundNum();
        //优化后，如果不对删掉
//        Map<String, List<AnalysisVO>> analysVos = getAnalysVos(rainStormAggVOS,stringStationMap);

        for (int i = 0; i < rainStormAggVOS.size(); i++) {
            RainStormAggVO rainStormAggVO = rainStormAggVOS.get(i);

            List<RainstormInfo> rainstormInfos = rainstormsByCourseAreas.get(rainStormAggVO.getCourseArea());
            Collections.sort(rainstormInfos,(a, b) -> {
                return (int)(a.getTime() - b.getTime());
            });
            //开始时间
            String startTime = String.valueOf(rainstormInfos.get(0).getTime());
            //结束时间
            String endTime = String.valueOf(rainstormInfos.get(rainstormInfos.size() - 1).getTime());
            //持续天数
            int continueDays = TimeUtil.getDaysBetween2Date(startTime, endTime);


            //优化前
//            AnalysisVO analysisVO =  new AnalysisVO();
            AnalysisVO analysisVO = this.getAnalysVos(rainStormAggVO.getCourseArea(), rainstormsByCourseAreas, startTime, endTime, continueDays);
            //优化后 可以和上面换
//            AnalysisVO analysisVO = analysVos.get(rainStormAggVO.getCourseArea()).get(0);


//            List<AffectStationInfoVO> affectStationInfoVOS = groupByStationNo.get(rainStormAggVO.getCourseArea());


            Map<String, DoubleSummaryStatistics> collect2 = rainstormInfos.stream().collect(Collectors.groupingBy(RainstormInfo::getStationNo,
                    Collectors.summarizingDouble(RainstormInfo::getRainFall)));

            List<AffectStationInfoVO> affectStationInfoVOS = new ArrayList<>();
            Collections.sort(rainstormInfos,(a, b) -> {
                return (int)(a.getTime() - b.getTime());
            });
            //根据站点分组
            Map<String, List<RainstormInfo>> collect1 = rainstormInfos.stream()
                    .collect(Collectors.groupingBy(RainstormInfo::getStationNo));
            collect1.forEach((k1,v1) -> {
                String stationNo = v1.get(0).getStationNo();
                Long st = v1.get(0).getTime();
                Long ed = v1.get(v1.size()-1).getTime();
                //单站数据
                AffectStationInfoVO affectStationInfoVO = new AffectStationInfoVO();
                affectStationInfoVO.setStationNo(stationNo);
                affectStationInfoVO.setLat(Double.parseDouble(stringStationMap.get(stationNo).getLat()));
                affectStationInfoVO.setLon(Double.parseDouble(stringStationMap.get(stationNo).getLon()));
                affectStationInfoVO.setStartTime(String.valueOf(st));
                affectStationInfoVO.setEndTime(String.valueOf(ed));
                affectStationInfoVO.setContinueDays(TimeUtil.getDaysBetween2Date(String.valueOf(st), String.valueOf(ed)));
                affectStationInfoVO.setTotalRainfall(NumUtil.save2Point(collect2.get(stationNo).getSum()/10));
                affectStationInfoVO.setAvgArea(NumUtil.save2Point(collect2.get(stationNo).getSum()/10/TimeUtil.getDaysBetween2Date(String.valueOf(st), String.valueOf(ed))));
                affectStationInfoVOS.add(affectStationInfoVO);
            });


            Collections.sort(affectStationInfoVOS,(a, b) -> {
                return (int)(Double.parseDouble(a.getStartTime()) - Double.parseDouble(b.getStartTime()));
            });
            //区域最小
            Collections.sort(affectStationInfoVOS,(a, b) -> {
                return (int)(a.getAvgArea() - b.getAvgArea());
            });
            analysisVO.setMinArea(affectStationInfoVOS.get(0).getAvgArea());

            //区域最大
            analysisVO.setMaxArea(affectStationInfoVOS.get(affectStationInfoVOS.size() - 1).getAvgArea());
            //todo 区域平均

            DoubleSummaryStatistics collect = affectStationInfoVOS.stream().collect(Collectors.summarizingDouble(AffectStationInfoVO::getAvgArea));
            analysisVO.setAvgArea(NumUtil.save2Point(collect.getAverage()));


            //计算边界
            QuickHull quickHull = new QuickHull();
            LinkedList pointSet = new LinkedList();
            List<Double> lats = new ArrayList<>();
            List<String> gridNums = new ArrayList<>();

            //循环所有影响的站点画圈圈
            BigDecimal afffectArea = new BigDecimal(0);
            for (int j = 0; j < affectStationInfoVOS.size(); j++) {
                AffectStationInfoVO affectStationInfoVO = affectStationInfoVOS.get(j);
                affectStationInfoVO.setRange(j+1);
//                String[] split = stringStationMap.get(affectStationInfoVO.getStationNo()).getBound().split(";");
//                Arrays.stream(split).forEach(x -> {
//                    String[] split1 = x.split(",");
//                    pointSet.insert(new Point2D.Double(Double.valueOf(split1[0]),Double.valueOf(split1[1])));
//                });

                pointSet.insertAll(map.get(affectStationInfoVO.getStationNo()));
//                pointSet.insert(new Point2D.Double(Double.valueOf(stringStationMap.get(affectStationInfoVO.getStationNo()).getLon()),Double.valueOf(stringStationMap.get(affectStationInfoVO.getStationNo()).getLat())));
//                lats.add(Double.valueOf(stringStationMap.get(affectStationInfoVO.getStationNo()).getLat()));

                String gridNum = stringStationMap.get(affectStationInfoVO.getStationNo()).getGridNum();
//                if (gridNums.contains(gridNum)){
//                    continue;
//                }
//                gridNums.add(gridNum);
//                lats.add(Double.valueOf(stringStationMap.get(affectStationInfoVO.getStationNo()).getLat()));
                List<Station> stations = boundNumMap.get(gridNum);
                double v = DistanceUtil.countArea(Double.parseDouble(stringStationMap.get(affectStationInfoVO.getStationNo()).getLat()));
                BigDecimal bigDecimal2 = new BigDecimal(v / stations.size());
                afffectArea = afffectArea.add(bigDecimal2);
            }

            LinkedList calcPointsSet = quickHull.useAlgorithm(pointSet);
            FeatureCollection draw = GeoUtil.draw(calcPointsSet, rainStormAggVO.getCourseArea());
            analysisVO.setFeatureCollection(draw);

            //算区域面积
//            double afffectArea = DistanceUtil.countAreas(lats);
//            BigDecimal bigDecimal = new BigDecimal(0);
//            for (String gridNum : gridNums) {
//                List<Station> stations = boundNumMap.get(gridNum);
//                double v = DistanceUtil.countArea(Double.parseDouble(stations.get(0).getLat()));
//                BigDecimal bigDecimal2 = new BigDecimal(v / stations.size());
//                afffectArea = afffectArea.add(bigDecimal2);
//            }
            analysisVO.setAfffectArea(NumUtil.save2Point(afffectArea.doubleValue()));
            //todo 平均降水量以过程的总降水量为主 不再是暴雨数据这张表了
//            double avgTotalRainfall = rainStormAggVO.getSum() /10 / affectStationInfoVOS.size()+1;

            //封装返回结果集
            analysisVO.setAffectStationInfoVOS(affectStationInfoVOS).setCourseArea(rainStormAggVO.getCourseArea())
                    .setContinueDays(continueDays).setStartTime(startTime).setEndTime(endTime);
            analysisVOS.add(analysisVO);
        }
        return analysisVOS;
    }


    private AnalysisVO getCopyAnalysVos(String courseArea, Map<String, List<RainstormFeatureInfo>> rainstormsByCourseAreas,String startTime, String endTime, Integer continueDays) {
        AnalysisVO analysisVO = new AnalysisVO();
        List<RainstormFeatureInfo> rainstormInfos = rainstormsByCourseAreas.get(courseArea);

        //区域影响的站点集合 需要根据时间去基础信息表差数据 因为总降水量不止包含暴雨数据
        List<String> arreaStations = rainstormInfos.stream().map(RainstormFeatureInfo::getStationNo).collect(Collectors.toList());
        EsCondition stationCondition = EsCondition.getEsCondition();
        stationCondition.in("stationNo", com.hxgis.common.utils.CollectionUtils.convertCollectionString(arreaStations));
        stationCondition.gte("time", Long.valueOf(startTime))
                .lte(Long.valueOf(endTime))
//                .gte("rainFall",500)
                .lte("rainFall",10000);
        stationCondition.size(1000000);
        List<RainDayInfo> rainDayInfos = rainDayInfoRepository.selectList(stationCondition);
        Map<String, DoubleSummaryStatistics> collect1 = rainDayInfos.stream().collect(Collectors.groupingBy(RainDayInfo::getStationNo,
                Collectors.summarizingDouble(RainDayInfo::getRainFall)));
        List<DoubleSummaryStatistics> doubleSummaryStatisticsList = new ArrayList<>();
        collect1.forEach((k1,v1) -> {
            doubleSummaryStatisticsList.add(collect1.get(k1));
        });
        //最大累计降水量
        Collections.sort(doubleSummaryStatisticsList,(a, b) -> {
            return new BigDecimal(b.getSum()).compareTo(new BigDecimal(a.getSum()));
        });
        analysisVO.setMaxTotalRainfall(NumUtil.save2Point(doubleSummaryStatisticsList.get(0).getSum() / 10));
        analysisVO.setMinTotalRainfall(NumUtil.save2Point(doubleSummaryStatisticsList.get(doubleSummaryStatisticsList.size() - 1).getSum() / 10));
        Double totalRainFall = new Double(0);
        for (DoubleSummaryStatistics doubleSummaryStatistics : doubleSummaryStatisticsList) {
            totalRainFall += doubleSummaryStatistics.getSum()/10;
        }
        analysisVO.setAvgTotalRainfall(NumUtil.save2Point(totalRainFall/doubleSummaryStatisticsList.size() + 1));
        return analysisVO;
    }



    private AnalysisVO getAnalysVos(String courseArea, Map<String, List<RainstormInfo>> rainstormsByCourseAreas,String startTime, String endTime, Integer continueDays) {
        AnalysisVO analysisVO = new AnalysisVO();
        List<RainstormInfo> rainstormInfos = rainstormsByCourseAreas.get(courseArea);

        //区域影响的站点集合 需要根据时间去基础信息表差数据 因为总降水量不止包含暴雨数据
        List<String> arreaStations = rainstormInfos.stream().map(RainstormInfo::getStationNo).collect(Collectors.toList());
        EsCondition stationCondition = EsCondition.getEsCondition().in("stationNo", com.hxgis.common.utils.CollectionUtils.convertCollectionString(arreaStations))
                .gte("time", Long.valueOf(startTime)).lte(Long.valueOf(endTime))
                .gte("rainFall", 0).lte(10000)
                .size(1000000);
        List<RainDayInfo> rainDayInfos = rainDayInfoRepository.selectList(stationCondition);
        Map<String, DoubleSummaryStatistics> collect1 = rainDayInfos.stream().collect(Collectors.groupingBy(RainDayInfo::getStationNo,
                Collectors.summarizingDouble(RainDayInfo::getRainFall)));
        List<DoubleSummaryStatistics> doubleSummaryStatisticsList = new ArrayList<>();
        collect1.forEach((k1,v1) -> {
            doubleSummaryStatisticsList.add(collect1.get(k1));
        });
        //最大累计降水量
        Collections.sort(doubleSummaryStatisticsList,(a, b) -> {
            return new BigDecimal(b.getSum()).compareTo(new BigDecimal(a.getSum()));
        });
        analysisVO.setMaxTotalRainfall(NumUtil.save2Point(doubleSummaryStatisticsList.get(0).getSum() / 10));
        analysisVO.setMinTotalRainfall(NumUtil.save2Point(doubleSummaryStatisticsList.get(doubleSummaryStatisticsList.size() - 1).getSum() / 10));
        Double totalRainFall = new Double(0);
        for (DoubleSummaryStatistics doubleSummaryStatistics : doubleSummaryStatisticsList) {
            totalRainFall += doubleSummaryStatistics.getSum()/10;
        }
        analysisVO.setAvgTotalRainfall(NumUtil.save2Point(totalRainFall/doubleSummaryStatisticsList.size() + 1));
//        analysisVO.setAvgTotalRainfall(NumUtil.save2Point(doubleSummaryStatisticsList.get(0).getAverage() / 10));
        return analysisVO;
    }






    private Map<String,List<AnalysisVO>> getAnalysVos(List<RainStormAggVO> rainStormAggVOS,Map<String, Station> stringStationMap) {
        List<AnalysisVO> analysisVOS = new ArrayList<>();
        Map<String,List<AnalysisVO>> stringListMap = new HashMap<>();
        EsCondition esCondition1 = EsCondition.getEsCondition();
        List<String> courseArreas = rainStormAggVOS.stream().map(RainStormAggVO::getCourseArea).collect(Collectors.toList());
        esCondition1.in("courseArea",courseArreas.toArray());
        esCondition1.size(1000000);
        List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(esCondition1);
        Map<String, List<RainstormInfo>> collect = rainstormInfos.stream().collect(Collectors.groupingBy(RainstormInfo::getCourseArea));
        //根据站点分组求  "53781" -> "DoubleSummaryStatistics{count=6, sum=2816.000000, min=342.000000, average=469.333333, max=633.000000}"
        Map<String, DoubleSummaryStatistics> collect2 = rainstormInfos.stream().collect(Collectors.groupingBy(RainstormInfo::getStationNo,
                Collectors.summarizingDouble(RainstormInfo::getRainFall)));

        collect.forEach((k,v) -> {
            AnalysisVO analysisVO = new AnalysisVO();
            List<AffectStationInfoVO> affectStationInfoVOS = new ArrayList<>();
            List<RainstormInfo> rainstormInfos1 = v;
            Collections.sort(rainstormInfos1,(a, b) -> {
                return (int)(a.getTime() - b.getTime());
            });
            //根据站点分组
            Map<String, List<RainstormInfo>> collect1 = rainstormInfos1.stream()
                    .collect(Collectors.groupingBy(RainstormInfo::getStationNo));
            List<DoubleSummaryStatistics> doubleSummaryStatisticsList = new ArrayList<>();
            collect1.forEach((k1,v1) -> {
                String stationNo = v1.get(0).getStationNo();
                doubleSummaryStatisticsList.add(collect2.get(stationNo));
            });
            //最大累计降水量
            Collections.sort(doubleSummaryStatisticsList,(a, b) -> {
                return new BigDecimal(b.getSum()).compareTo(new BigDecimal(a.getSum()));
            });
            analysisVO.setMaxTotalRainfall(NumUtil.save2Point(doubleSummaryStatisticsList.get(0).getSum()/10));
            //最小累计降水量
            Collections.sort(doubleSummaryStatisticsList,(a, b) -> {
                return new BigDecimal(a.getSum()).compareTo(new BigDecimal(b.getSum()));
            });
            analysisVO.setMinTotalRainfall(NumUtil.save2Point(doubleSummaryStatisticsList.get(0).getSum()/10));
            //区域最大
            Collections.sort(doubleSummaryStatisticsList,(a, b) -> {
                return new BigDecimal(b.getAverage()).compareTo(new BigDecimal(a.getAverage()));
            });
            analysisVO.setMaxArea(NumUtil.save2Point(doubleSummaryStatisticsList.get(0).getAverage()/10));
            //区域最小
            Collections.sort(doubleSummaryStatisticsList,(a, b) -> {
                return new BigDecimal(a.getAverage()).compareTo(new BigDecimal(b.getAverage()));
            });
            analysisVO.setMinArea(NumUtil.save2Point(doubleSummaryStatisticsList.get(0).getAverage()/10));
            analysisVO.setCourseArea(k);
            analysisVOS.add(analysisVO);
        });
        return analysisVOS.stream().collect(Collectors.groupingBy(AnalysisVO::getCourseArea));
    }


    private Map<String, List<Station>> getBoundNum(){
        List<Station> stations = StationCache.getStations();
        Map<String, List<Station>> collect = stations.stream().collect(Collectors.groupingBy(Station::getGridNum));
        return collect;
    }


    //string -》 courseNum  单站点的一些信息
    private Map<String,List<AffectStationInfoVO>> groupCopyByStationNo(List<RainStormAggVO> rainStormAggVOS,Map<String, Station> stringStationMap) {

        //根据过程编号
        Map<String,List<AffectStationInfoVO>> map = new HashMap<>();
        EsCondition esCondition1 = EsCondition.getEsCondition();
        List<String> courseArreas = rainStormAggVOS.stream().map(RainStormAggVO::getCourseArea).collect(Collectors.toList());
        esCondition1.in("courseArea",courseArreas.toArray());
        esCondition1.size(1000000);
        List<RainstormFeatureInfo> rainstormFeatureInfos = featureInfoRepository.selectList(esCondition1);
        Map<String, List<RainstormFeatureInfo>> collect = rainstormFeatureInfos.stream().collect(Collectors.groupingBy(RainstormFeatureInfo::getCourseArea));

        //根据站点分组求  "53781" -> "DoubleSummaryStatistics{count=6, sum=2816.000000, min=342.000000, average=469.333333, max=633.000000}"
        Map<String, DoubleSummaryStatistics> collect2 = rainstormFeatureInfos.stream().collect(Collectors.groupingBy(RainstormFeatureInfo::getStationNo,
                Collectors.summarizingDouble(RainstormFeatureInfo::getRainFall)));

        collect.forEach((k,v) -> {
            List<AffectStationInfoVO> affectStationInfoVOS = new ArrayList<>();
            List<RainstormFeatureInfo> rainstormInfos1 = v;
            Collections.sort(rainstormInfos1,(a, b) -> {
                return (int)(a.getTime() - b.getTime());
            });
            //根据站点分组
            Map<String, List<RainstormFeatureInfo>> collect1 = rainstormInfos1.stream()
                    .collect(Collectors.groupingBy(RainstormFeatureInfo::getStationNo));
            collect1.forEach((k1,v1) -> {
                Long startTime = v1.get(0).getTime();
                Long endTime = v1.get(v1.size()-1).getTime();
                String stationNo = v1.get(0).getStationNo();
                //单站数据
                AffectStationInfoVO affectStationInfoVO = new AffectStationInfoVO();
                affectStationInfoVO.setStartTime(String.valueOf(startTime)).setEndTime(String.valueOf(endTime))
                        .setStationNo(stationNo).setLat(Double.parseDouble(stringStationMap.get(stationNo).getLat()))
                        .setLon(Double.parseDouble(stringStationMap.get(stationNo).getLon()))
                        .setContinueDays(TimeUtil.getDaysBetween2Date(String.valueOf(startTime), String.valueOf(endTime)))
                        .setTotalRainfall(NumUtil.save2Point(collect2.get(stationNo).getSum()/10))
                        .setAvgArea(NumUtil.save2Point(collect2.get(stationNo).getSum()/10/TimeUtil.getDaysBetween2Date(String.valueOf(startTime), String.valueOf(endTime))));
                affectStationInfoVOS.add(affectStationInfoVO);
            });
            map.put(k,affectStationInfoVOS);
        });
        return map;
    }





    //string -》 courseNum  单站点的一些信息
    private Map<String,List<AffectStationInfoVO>> groupByStationNo(List<RainStormAggVO> rainStormAggVOS,Map<String, Station> stringStationMap) {

        //根据过程编号
        Map<String,List<AffectStationInfoVO>> map = new HashMap<>();
        EsCondition esCondition1 = EsCondition.getEsCondition();
        List<String> courseArreas = rainStormAggVOS.stream().map(RainStormAggVO::getCourseArea).collect(Collectors.toList());
        esCondition1.in("courseArea",courseArreas.toArray());
        esCondition1.lte("rainFall",10000);
        esCondition1.size(1000000);
        List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(esCondition1);
        Map<String, List<RainstormInfo>> collect = rainstormInfos.stream().collect(Collectors.groupingBy(RainstormInfo::getCourseArea));

        //根据站点分组求  "53781" -> "DoubleSummaryStatistics{count=6, sum=2816.000000, min=342.000000, average=469.333333, max=633.000000}"
        Map<String, DoubleSummaryStatistics> collect2 = rainstormInfos.stream().collect(Collectors.groupingBy(RainstormInfo::getStationNo,
                Collectors.summarizingDouble(RainstormInfo::getRainFall)));

        collect.forEach((k,v) -> {
            List<AffectStationInfoVO> affectStationInfoVOS = new ArrayList<>();
            List<RainstormInfo> rainstormInfos1 = v;
            Collections.sort(rainstormInfos1,(a, b) -> {
                return (int)(a.getTime() - b.getTime());
            });
            //根据站点分组
            Map<String, List<RainstormInfo>> collect1 = rainstormInfos1.stream()
                    .collect(Collectors.groupingBy(RainstormInfo::getStationNo));
            collect1.forEach((k1,v1) -> {
                String stationNo = v1.get(0).getStationNo();
                Long startTime = v1.get(0).getTime();
                Long endTime = v1.get(v1.size()-1).getTime();
                //单站数据
                AffectStationInfoVO affectStationInfoVO = new AffectStationInfoVO();
                affectStationInfoVO.setStartTime(String.valueOf(startTime));
                affectStationInfoVO.setEndTime(String.valueOf(endTime));
                affectStationInfoVO.setStationNo(stationNo);
                affectStationInfoVO.setLat(Double.parseDouble(stringStationMap.get(stationNo).getLat()));
                affectStationInfoVO.setLon(Double.parseDouble(stringStationMap.get(stationNo).getLon()));
                affectStationInfoVO.setContinueDays(TimeUtil.getDaysBetween2Date(String.valueOf(startTime), String.valueOf(endTime)));
                affectStationInfoVO.setTotalRainfall(NumUtil.save2Point(collect2.get(stationNo).getSum()/10));
                affectStationInfoVO.setAvgArea(NumUtil.save2Point(collect2.get(stationNo).getSum()/10/TimeUtil.getDaysBetween2Date(String.valueOf(startTime), String.valueOf(endTime))));
                affectStationInfoVOS.add(affectStationInfoVO);
            });
            map.put(k,affectStationInfoVOS);
        });
        return map;
    }

    private Map<String, List<RainstormFeatureInfo>> getCopyRainstormsByCourseAreas(List<RainStormAggVO> rainStormAggVOS) {
        EsCondition esCondition1 = EsCondition.getEsCondition();
        List<String> courseArreas = rainStormAggVOS.stream().map(RainStormAggVO::getCourseArea).collect(Collectors.toList());
        esCondition1.in("courseArea",courseArreas.toArray());
        esCondition1.lte("rainFall",10000);
        esCondition1.size(1000000);
        List<RainstormFeatureInfo> featureInfos = featureInfoRepository.selectList(esCondition1);
        Map<String, List<RainstormFeatureInfo>> collect = featureInfos.stream().collect(Collectors.groupingBy(RainstormFeatureInfo::getCourseArea));
        return collect;
    }

    /**
     * 到这里可以赛选站点区分什么型
     * @param rainStormAggVOS
     * @return
     */
    private Map<String, List<RainstormInfo>> getRainstormsByCourseAreas(List<RainStormAggVO> rainStormAggVOS) {
        EsCondition esCondition1 = EsCondition.getEsCondition();
        List<String> courseArreas = rainStormAggVOS.stream().map(RainStormAggVO::getCourseArea).collect(Collectors.toList());
        esCondition1.in("courseArea",courseArreas.toArray());
        esCondition1.lte("rainFall",10000);
        esCondition1.size(1000000);
        List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(esCondition1);
        Map<String, List<RainstormInfo>> collect = rainstormInfos.stream().collect(Collectors.groupingBy(RainstormInfo::getCourseArea));
        return collect;
    }


    /**
     * todo 同步区域的信息去rain_storm_info   补全 courseArea
     * @param totalAreaStations
     */
    private void sychAreaToEs(List<Set<String>> totalAreaStations){
        Set<String> noRepeatCourseNum = new HashSet<>();
        totalAreaStations.stream().forEach(x -> {
            x.stream().forEach(y -> {
                noRepeatCourseNum.add(y);
            });
        });
        EsCondition esCondition = EsCondition.getEsCondition();
        esCondition.in("courseNum",noRepeatCourseNum.toArray());
        esCondition.size(1000000);
        List<RainstormInfo> rainstormInfos = rainstormInfoRepository.selectList(esCondition);
        Map<String, List<RainstormInfo>> collect = rainstormInfos.stream().collect(Collectors.groupingBy(RainstormInfo::getCourseNum));
        List<RainstormInfo> totalRainstormInfos = new ArrayList<>();
        for (Set<String> totalAreaStation : totalAreaStations) {
            //生成唯一标识
            String uuid = UUID.randomUUID().toString().replace("-", "");
            //这里才算一个过程的
            for (String s : totalAreaStation) {
                List<RainstormInfo> rainstormInfos1 = collect.get(s);
//                Set<String> stations = new HashSet<>();
//                rainstormInfos1.stream().forEach(x -> {
//                    stations.add(x.getStationNo());
//                });
                if (rainstormInfos1.size() >= 3){
                    for (RainstormInfo rainstormInfo : rainstormInfos1) {
                        rainstormInfo.setCourseArea(uuid);
//                    totalRainstormInfos.add(rainstormInfo);
                    }
                    totalRainstormInfos.addAll(rainstormInfos1);
                }
            }
        }
        //更新数据操作
        int i = rainstormInfoRepository.saveBatch(totalRainstormInfos);
        System.out.println(rainstormInfos.size());


    }


    /**
     * 转换 往前找一天 往后找两天 注意第一天 和最后一天两个特殊情况 避免频繁查es
     * @param rainstormInfoOlds
     * @return
     */
    private List<RainstormInfo> transSingleStrom(List<RainstormInfo> rainstormInfoOlds){
        List<RainstormInfo> rainstormInfoNew = new ArrayList<>();
        Map<Long, RainstormInfo> rainstormInfoMap = rainstormInfoOlds.stream().collect(Collectors.toMap(RainstormInfo::getTime, value -> value));
        /**
         * 1.只查第一条的前一天数据
         * 2.查询最后一条的后两天数据
         */
        for (int i = 0; i < rainstormInfoOlds.size(); i++) {
            RainstormInfo rainstormInfo = rainstormInfoOlds.get(i);
            String preDay = TimeUtil.preDay(rainstormInfo.getTime().toString(), 1, TimeUtil.FORMATOR_YMD);
            String nextDay1 = TimeUtil.nextDay(rainstormInfo.getTime().toString(), 1, TimeUtil.FORMATOR_YMD);
            String nextDay2 = TimeUtil.nextDay(rainstormInfo.getTime().toString(), 2, TimeUtil.FORMATOR_YMD);
            if (i == 0){
                RainstormInfo rainstormInfo_pre = queryByTime(Long.parseLong(preDay), rainstormInfo.getStationNo());
//                if (Objects.isNull(rainstormInfo_pre) || rainstormInfo_pre.getCourseNum() == null){
//                    RainstormInfo rainstormInfo2 = rainstormInfoMap.get(Long.valueOf(nextDay2));
//                    RainstormInfo rainstormInfo1 = rainstormInfoMap.get(Long.valueOf(nextDay1));
//                    if (Objects.nonNull(rainstormInfo1) && Objects.nonNull(rainstormInfo2)){
//                        rainstormInfo.setCourseNum(rainstormInfo.getStationNo() + rainstormInfo.getTime());
//                    }else{
//                        rainstormInfo.setCourseNum(null);
//                    }
//                }else{
//                    rainstormInfo.setCourseNum(rainstormInfo_pre.getCourseNum());
//                }
                if(Objects.nonNull(rainstormInfo_pre)){
                    //todo 再判断courseNum是不是空
                    if(rainstormInfo_pre.getCourseNum() == null){
                        RainstormInfo rainstormInfo1 = rainstormInfoMap.get(Long.valueOf(nextDay1));
                        if (Objects.nonNull(rainstormInfo1)){
                            //todo 前一天的也需要设置下
                            rainstormInfo_pre.setCourseNum(rainstormInfo_pre.getStationNo() + rainstormInfo_pre.getTime());
                            rainstormInfo.setCourseNum(rainstormInfo_pre.getCourseNum());
                            rainstormInfoNew.add(rainstormInfo_pre);
                        }
                    }else{
                        rainstormInfo.setCourseNum(rainstormInfo_pre.getCourseNum());
                    }
                }else{
                    RainstormInfo rainstormInfo2 = rainstormInfoMap.get(Long.valueOf(nextDay2));
                    RainstormInfo rainstormInfo1 = rainstormInfoMap.get(Long.valueOf(nextDay1));
                    if (Objects.nonNull(rainstormInfo1) && Objects.nonNull(rainstormInfo2)){
                        rainstormInfo.setCourseNum(rainstormInfo.getStationNo() + rainstormInfo.getTime());
                    }else{
                        rainstormInfo.setCourseNum(null);
                    }
                }
            }else if (i == rainstormInfoOlds.size() - 1){
                RainstormInfo rainstormInfo_pre = rainstormInfoMap.get(Long.parseLong(preDay));
                if (Objects.isNull(rainstormInfo_pre) || rainstormInfo_pre.getCourseNum() == null){
                    //如果是数据提前准备好了就可以这样，不是处理好的就需要去raindayinfo这张表查询
                    RainstormInfo rainstormInfo1 = queryByTime(Long.parseLong(nextDay1), rainstormInfo.getStationNo());
                    RainstormInfo rainstormInfo2 = queryByTime(Long.parseLong(nextDay2), rainstormInfo.getStationNo());

                    //todo 优化后可以不用把所有的暴雨数据入暴雨表
//                    RainDayInfo rainDayInfo1 = featureService.queryRainFallByTime(Long.parseLong(nextDay1), rainstormInfo.getStationNo());
//                    RainDayInfo rainDayInfo2 = featureService.queryRainFallByTime(Long.parseLong(nextDay2), rainstormInfo.getStationNo());
//                    if (Objects.nonNull(rainDayInfo1) && rainDayInfo1.getRainFall() >= 500 && Objects.nonNull(rainDayInfo2) && rainDayInfo2.getRainFall() >= 500){
//                        rainstormInfo.setCourseNum(rainstormInfo.getStationNo() + rainstormInfo.getTime());
//                    }else{
//                        rainstormInfo.setCourseNum(null);
//                    }

                    //todo 如果是数据提前准备好了就可以这样，不是处理好的就需要去raindayinfo这张表查询
                    if (Objects.nonNull(rainstormInfo1) && Objects.nonNull(rainstormInfo2)){
                        rainstormInfo.setCourseNum(rainstormInfo.getStationNo() + rainstormInfo.getTime());
                    }else{
                        rainstormInfo.setCourseNum(null);
                    }



                }else{
                    rainstormInfo.setCourseNum(rainstormInfo_pre.getCourseNum());
                }
            }else if (i == rainstormInfoOlds.size() - 2){
                //todo 倒数第二个需要特殊处理下
                RainstormInfo rainstormInfo_pre = rainstormInfoMap.get(Long.parseLong(preDay));
                if (Objects.isNull(rainstormInfo_pre) || rainstormInfo_pre.getCourseNum() == null){

                    //todo 如果是数据提前准备好了就可以这样，不是处理好的就需要去raindayinfo这张表查询
                    RainstormInfo rainstormInfo1 = rainstormInfoMap.get(Long.valueOf(nextDay1));
                    RainstormInfo rainstormInfo2 = queryByTime(Long.parseLong(nextDay2), rainstormInfo.getStationNo());
                    if (Objects.nonNull(rainstormInfo1) && Objects.nonNull(rainstormInfo2)){
                        rainstormInfo.setCourseNum(rainstormInfo.getStationNo() + rainstormInfo.getTime());
                    }else{
                        rainstormInfo.setCourseNum(null);
                    }

                    //todo 优化后 优化后可以不用把所有的暴雨数据入暴雨表
//                    RainstormInfo rainstormInfo1 = rainstormInfoMap.get(Long.valueOf(nextDay1));
//                    RainDayInfo rainDayInfo2 = featureService.queryRainFallByTime(Long.parseLong(nextDay2), rainstormInfo.getStationNo());
//                    if (Objects.nonNull(rainstormInfo1) && Objects.nonNull(rainDayInfo2) && rainDayInfo2.getRainFall() >= 500){
//                        rainstormInfo.setCourseNum(rainstormInfo.getStationNo() + rainstormInfo.getTime());
//                    }else{
//                        rainstormInfo.setCourseNum(null);
//                    }

                }else{
                    rainstormInfo.setCourseNum(rainstormInfo_pre.getCourseNum());
                }
            }else{
                RainstormInfo rainstormInfo_pre = rainstormInfoMap.get(Long.parseLong(preDay));
                if (Objects.isNull(rainstormInfo_pre) || rainstormInfo_pre.getCourseNum() == null){
                    RainstormInfo rainstormInfo1 = rainstormInfoMap.get(Long.valueOf(nextDay1));
                    RainstormInfo rainstormInfo2 = rainstormInfoMap.get(Long.valueOf(nextDay2));
                    if (Objects.nonNull(rainstormInfo1) && Objects.nonNull(rainstormInfo2)){
                        rainstormInfo.setCourseNum(rainstormInfo.getStationNo() + rainstormInfo.getTime());
                    }else{
                        rainstormInfo.setCourseNum(null);
                    }
                }else{
                    rainstormInfo.setCourseNum(rainstormInfo_pre.getCourseNum());
                }
            }
        }
        rainstormInfoNew.addAll(rainstormInfoOlds);
        return rainstormInfoNew;
    }


}
